home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / asm_subr.arc / MBINDIV < prev    next >
Encoding:
Text File  |  1985-12-28  |  5.0 KB  |  208 lines

  1. ;-------------------------mbindiv routine begins--------------------------+
  2. ; from BLUEBOOK OF ASSEMBLY ROUTINES FOR IBM PC & XT.
  3. ;         page : 122
  4. ;
  5. ; NAME  MBINDIV
  6. ;
  7. ; ROUTINE FOR Multidigit Binary DIVISION
  8. ;
  9. ; FUNCTION: This routine divides two multidigit binary numbers, producing
  10. ; both a quotient and remainder.
  11. ;
  12. ; INPUT: Upon entry DS:SI points to the divisor; DS:BX points to where
  13. ; the dividend is upon entry and where the remainder will be upon exit,
  14. ; and DS:DI points to the location where the quotient will be upon exit.
  15. ; The size of these multidigit numbers is controlled by the constant
  16. ; ISIZE.  The divisor and quotient contain 16*ISIZE number of
  17. ; bits and the dividend and remainder have double that precision.
  18. ; Both the divisor and the quotient are stored in ISIZE number of 16-bit
  19. ; words of memory and the dividend and remainder are stored in 2*ISIZE
  20. ; number of 16-bit words of memory.
  21. ;
  22. ; OUTPUT: Upon exit DS:BX points to where the quotient is stored and
  23. ; DS:DI points to where the remainder is stored.
  24. ;
  25. ; REGISTERS USED:  No registers are modified.
  26. ;
  27. ; SEGMENTS REFERENCED:  Upon entry the data segment must contain
  28. ; storage for the multidigit numbers described above.
  29. ;
  30. ; ROUTINES CALLED:  None
  31. ;
  32. ; SPECIAL NOTES: None
  33. ;
  34. ; LOCAL SUBROUTINE TO COMPARE DIVISOR AGAINST DIVIDEND
  35. ;
  36. divcmp    proc    near
  37. ;
  38.     push    si        ; save registers
  39.     push    di
  40.     push    cx
  41. ;
  42.     std            ; backward direction
  43.     add    si,4*isize-2    ; point to end of temp divisor
  44.     add    di,4*isize-2    ; point to end of quotient
  45.     mov    cx,2*isize    ; count for double precision
  46. ;
  47.     repz    cmpsw        ; compare 'digit' by 'digit'
  48. ;
  49.     pop    cx        ; restore registers
  50.     pop    di
  51.     poop    si
  52.     ret            ; return from divcmp
  53. ;
  54. ; LOCAL SUBROUTINE FOR ARITHMETIC SHIFT DIVISOR LEFT
  55. ;
  56. divsal    proc    near
  57. ;
  58.     push    si        ; save registers
  59.     push    cx
  60. ;
  61.     mov    cx,2*isize    ; set counter
  62.     clc            ; clear carry in
  63. ;
  64. divsal1:
  65.     rcl    word ptr [si],1    ; shift one word by one bit
  66.     inc    si        ; point to next word
  67.     inc    si
  68.     loop    divsal1        ; loop through entire divisor
  69. ;
  70.     pop    cx        ; restore registers
  71.     pop    si
  72.     ret            ; return from divsal
  73. ;
  74. divsal    endp
  75. ;
  76. ; LOCAL SUBROUTINE FOR LOGICAL SHIFT DIVISOR RIGHT
  77. ;
  78. divslr    proc    near
  79. ;
  80.     push    si        ; save registers
  81.     push     cx
  82. ;
  83.     add    si,4*isize-2    ; poin to end of temp divisor
  84.     mov    cx,2*isize    ; count for double precision
  85.     clc            ; clear carry in
  86. ;
  87. divslr1:
  88.     rcr    word ptr [si],1    ; shift one word by one bit
  89.     inc    si        ; point to next word
  90.     inc    si
  91.     loop    divslr1        ; loop through entire divisor
  92. ;
  93.     pop    cx        ; restore registers
  94.     pop    si
  95.     ret            ; return from divslr
  96. ;
  97. divslr    endp
  98. ;
  99. ; LOCAL SUBROUTINE TO SUBTRACT SHIFTED DIVISOR FROM DIVIDEND
  100. ;
  101. divsub    proc    near
  102. ;
  103.     push    si        ; save registers
  104.     push    di
  105.     push    cx
  106. ;
  107.     clc            ; clear carry in
  108.     mov    cx,2*isize    ; set count fop double precision
  109. ;
  110. divsub1:
  111.     mov    ax,[si]        ; get word from shifted divisor
  112.     inc    si        ; point to next word
  113.     inc    si
  114.     sbb    [di],ax        ; subtract from word of dividend
  115.     inc    di        ; point to next word
  116.     inc    di
  117.     loop    divsub1        ; loop through all words
  118. ;
  119.     pop    cx
  120.     pop    di
  121.     pop    si
  122. ;
  123.     ret            ; return from divsub
  124. ;
  125. divsub    endp
  126. ;
  127. ; LOCAL SUBROUTINE TO SHIFT QUOTIENT LEFT
  128. ;
  129. quotshl    proc    near
  130. ;
  131.     push    bx        ; save registers
  132.     push    cx
  133. ;
  134.     mov    cx,isize    ; count for single precision
  135. ;
  136. quotshl1:
  137.     rcl    word ptr [bx],1    ; shift word of quotient left once
  138.     inc    bx        ; point to next word
  139.     inc    bx
  140.     loop    quotshl1    ; loop through entire quotient
  141. ;
  142.     pop    cx        ; restore registers
  143.     pop    bx
  144.     ret            ; retirn from quotshl
  145. ;
  146. quotshl    endp
  147. ;
  148. ; ROUTINE TO DIVIDE MULTIDIGIT BINARY NUMBERS
  149. ;
  150. mbindiv    proc    far
  151. ;
  152.     push    si        ; save registers
  153.     push    di
  154.     push    bx
  155.     push    cx
  156.     push    ax
  157. ;
  158. ; put single precision divisor into double precision location
  159.     push    di        ; save dividend pointer
  160.     lea    di,tempdiv    ; point to temporary divisor
  161.     mov    cx,isize    ; for a count of isize
  162.     cld            ; forward direction
  163.     rep    movsw        ; make the transfer
  164. ;
  165. ; clear upper part of double precision location
  166.     mov    ax,0        ; zero word
  167.     mov    cx,isize    ; for a count of isize
  168.     rep    stosw        ; clear the rest of the words
  169. ;
  170. ; restore dividend pointer and point to temp divisor
  171.     pop    di        ; restore dividend pointer
  172.     lea    si,tempdiv    ; point SI to temporary divisor
  173. ;
  174. ; initialize shift count
  175.     mov    cx,1        ; initial count of one
  176. ;
  177. ; normalize divisor
  178. mbindiv1:
  179.     test    msbdiv,8000h    ; test msb of divisor
  180.     jnz    mbindiv2    ; exit if normalized
  181.     call    divsal        ; arithmetic shift if not
  182.     inc    cx        ; count the shift
  183.     jmp    mbindiv1    ; keep on looping until normalized
  184. ;
  185. ; compare, subtract, shift loop
  186. mbindiv2:
  187.     call    divcmp        ; compare divisor against dividend
  188.     ja    mbindiv3    ; skip if too large
  189.     call    divsub        ; subtract if OK
  190.     stc            ; new bit of quotient is 1
  191.     jmp    mbindiv4    ; jump to end of loop
  192. ;
  193. mbindiv3:
  194.     clc            ; new bit of quotient is 0
  195. ;
  196. mbindiv4:
  197.     call    quotshl        ; shift bit into the quotient
  198.     call    divslr        ; logical shift divisor right once
  199.     loop    mbindiv2    ; loop for next digit
  200. ;
  201.     pop    ax        ; restore registers
  202.     pop    cx
  203.     pop    bx
  204.     pop    di
  205.     pop    si
  206. ;
  207. mbindiv    endp
  208. ;-------------------------mbindiv routine ends---------------------------